package com.citybox.shared.web;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONWriter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Domain基类
 */
@Data
@Slf4j
public class BaseDomain implements Serializable {

    /**
     * 自定义请求参数
     */
    //private Map<String, Object> params;

    /**
     * DO 转 POJO（DTO/VO）
     */
    public <T> T toData(Class<T> clazz) {
        return toData(clazz, this);
    }

    /**
     * DO 转 Entity（数据库实体类）
     */
    public <T> T toEntity(Class<T> clazz) {
        return toEntity(clazz, this);
    }

    /**
     * 通用 Data 转换器（DO -> DTO/POJO）
     */
    public static <D, V> V toData(Class<V> clazz, D value) {
        try {
            if (value == null) {
                return null;
            }
            V object = clazz.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(value, object);

            Field[] fields = getAllFieldsRecursive(value.getClass());
            Map<String, Field> dataFieldMap = Arrays.stream(getAllFieldsRecursive(clazz))
                    .peek(item -> item.setAccessible(true))
                    .collect(Collectors.toMap(item -> item.getName().toLowerCase(), item -> item, (a, b) -> a));

            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName().toLowerCase();
                if (dataFieldMap.containsKey(fieldName) && field.get(value) != null) {
                    Field dataField = dataFieldMap.get(fieldName);
                    Object json = JSON.toJSON(field.get(value), JSONWriter.Feature.WriteEnumUsingToString);
                    Type type = dataField.getGenericType();
                    if (json instanceof JSONArray && type instanceof ParameterizedType parameterizedType) {
                        Class<?> genericType = (Class<?>) parameterizedType.getActualTypeArguments()[0];
                        dataField.set(object, JSON.parseArray(json.toString(), genericType));
                    } else {
                        dataField.set(object, JSON.to(dataField.getType(), json));
                    }
                }
            }
            return object;
        } catch (Exception e) {
            log.error("DO -> POJO 转换失败", e);
            throw new RuntimeException("数据转换异常: " + e.getMessage(), e);
        }
    }

    /**
     * 通用 Entity 转换器（DO -> Entity）
     */
    public static <D> D toEntity(Class<D> clazz, Object value) {
        try {
            if (value == null) {
                return null;
            }
            D object = clazz.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(value, object);

            Field[] fields = getAllFieldsRecursive(clazz);
            Map<String, Field> oldFieldMap = Arrays.stream(getAllFieldsRecursive(value.getClass()))
                    .peek(item -> item.setAccessible(true))
                    .collect(Collectors.toMap(item -> item.getName().toLowerCase(), item -> item, (a, b) -> a));

            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName().toLowerCase();
                if (oldFieldMap.containsKey(fieldName)) {
                    Field entityField = oldFieldMap.get(fieldName);
                    entityField.setAccessible(true);
                    Object entityValue = entityField.get(value);

                    if (entityValue != null) {
                        // 如果是枚举类型的字段，处理成枚举对象
                        if (field.getType().isEnum()) {
                            field.set(object, Enum.valueOf((Class<Enum>) field.getType(), entityValue.toString()));
                        } else {
                            // 修复这里的问题：确保类型兼容
                            if (field.getType().isAssignableFrom(entityValue.getClass())) {
                                field.set(object, entityValue);
                            } else {
                                // 类型不匹配时进行转换
                                Object convertedValue = convertValue(entityValue, field.getType());
                                field.set(object, convertedValue);
                            }
                        }
                    }
                }
            }
            return object;
        } catch (Exception e) {
            log.error("DO -> Entity 转换失败", e);
            throw new RuntimeException("数据转换异常: " + e.getMessage(), e);
        }
    }

    /**
     * 值类型转换辅助方法
     */
    private static Object convertValue(Object value, Class<?> targetType) {
        if (value == null) {
            return null;
        }

        // 处理相同类型的情况
        if (targetType.equals(value.getClass())) {
            return value;
        }

        // Long类型转换
        if (targetType.equals(Long.class) || targetType.equals(long.class)) {
            if (value instanceof Number) {
                return ((Number) value).longValue();
            } else if (value instanceof String) {
                try {
                    return Long.parseLong((String) value);
                } catch (NumberFormatException e) {
                    return 0L;
                }
            }
        }
        // Integer类型转换
        else if (targetType.equals(Integer.class) || targetType.equals(int.class)) {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            } else if (value instanceof String) {
                try {
                    return Integer.parseInt((String) value);
                } catch (NumberFormatException e) {
                    return 0;
                }
            }
        }
        // String类型转换
        else if (targetType.equals(String.class)) {
            return value.toString();
        }

        // 默认使用JSON转换（保持与原逻辑一致）
        try {
            return JSON.to(targetType, value);
        } catch (Exception e) {
            log.warn("字段类型转换失败，使用原始值: {}", e.getMessage());
            return value;
        }
    }

    /**
     * 递归获取所有字段（包括父类）
     */
    public static Field[] getAllFieldsRecursive(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null && !Object.class.equals(clazz)) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fields.toArray(new Field[0]);
    }
}